package com.ywgt.utils;

import io.jsonwebtoken.*;
import org.springframework.security.core.userdetails.UserDetails;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;


public class JWTUtil {

    private static final String SECRET="ASDF5DS21FSVXVXC";

    private static final Long MILLIS=3600000L;

    /**
     * 生成token
     * @param id  token的唯一性标识
     * @param subject token的payload
     * @param millis token有效时长，默认为1小时
     * @return
     */
    public static String getToken(String id, String subject,Long millis){
        //指定使用使用的加密算法
        SignatureAlgorithm signatureAlgorithm=SignatureAlgorithm.HS256;
        //当前时间
        Long currentMillis=System.currentTimeMillis();
        //如果传入的参数为null
        if (millis==null){
            millis=MILLIS;
        }
        //计算过期时间
        Date expiry = new Date(millis + currentMillis);
        //生成秘钥(使用AES 对称加密算法)
        SecretKey secretKey = getSecretKey();
        //生成token
        String token = Jwts.builder().setId(id)
                .setExpiration(expiry)
                .setSubject(subject)
                .claim("expiry",expiry)
                .setIssuer("admin")
                .setIssuedAt(new Date())
                .signWith(signatureAlgorithm, secretKey)
                .compact();
        return token;
    }
    /**
     * key - 密钥的密钥材料。 将复制以offset开头的数组的第一个len字节，以防止后续修改。
     * offset - 密钥材料开始的 key中的偏移量。
     * len - 密钥材料的长度。
     * algorithm - 与给定密钥材料关联的密钥算法的名称。 有关标准算法名称的信息，请参见Java Security Standard Algorithm Names文档。
     * Advanced Encryption Standard
     * @return 返回秘钥
     */
    public static SecretKey getSecretKey(){
        byte[] decode = Base64.getDecoder().decode(SECRET);
        SecretKey secretKey=new SecretKeySpec(decode,0,decode.length,"AES");
        return secretKey;
    }

    /**
     * 根据用户判断token是否有效
     * @param token
     * @param userDetails
     * @return true代表有效
     * @throws Exception
     */
    public static boolean volidateToken(String token, UserDetails userDetails) throws Exception {
        String username = parseJwtClaims(token);
        return username.equals(userDetails.getUsername())&&!isExpired(token);
    }

    /**
     * 判断token是否过期，
     * @param token
     * @return true代表未过期
     * @throws Exception
     */
    public static boolean isExpired(String token)throws Exception{
        SecretKey secretKey = getSecretKey();
        Claims claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
        Date expiration = claims.getExpiration();
        return expiration.before(new Date());
    }

    /**
     * 解析传入的JWT令牌的payload
     * @param JWT
     * @return 返回 Claims对象
     */
    public static String parseJwtClaims(String JWT)throws Exception{
        SecretKey secretKey = getSecretKey();
        return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(JWT).getBody().getSubject();
    }

}
